home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / doc.lha / doc.doc / prepro.doc < prev    next >
Text File  |  1992-09-25  |  42KB  |  1,545 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11. ___________________________________________________________________
  12.  
  13.  
  14.                                    Preprocessors
  15.  
  16.  
  17.                                    J. Grosch
  18.  
  19.  
  20. ___________________________________________________________________
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50. ___________________________________________________________________
  51.                                    GESELLSCHAFT FUeR MATHEMATIK
  52.                                    UND DATENVERARBEITUNG MBH
  53.  
  54.                                    FORSCHUNGSSTELLE FUeR
  55.                                    PROGRAMMSTRUKTUREN
  56.                                    AN DER UNIVERSITAeT KARLSRUHE
  57. ___________________________________________________________________
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.                                    Project
  76.  
  77.                              Compiler Generation
  78.  
  79.          ___________________________________________________________
  80.  
  81.                                 Preprocessors
  82.  
  83.  
  84.                                  Josef Grosch
  85.  
  86.  
  87.                                  Aug. 4, 1992
  88.  
  89.          ___________________________________________________________
  90.  
  91.  
  92.                                 Report No. 24
  93.  
  94.  
  95.                              Copyright c 1992 GMD
  96.  
  97.  
  98.             Gesellschaft fuer Mathematik und Datenverarbeitung mbH
  99.                 Forschungsstelle an der Universitaet Karlsruhe
  100.                           Vincenz-Priesznitz-Str. 1
  101.                                D-7500 Karlsruhe
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.                                                                              1
  135.  
  136.  
  137.                                 Preprocessors
  138.  
  139.  
  140. 1.  Introduction
  141.  
  142. This manual describes the features and the usage of two kinds of preprocessors
  143. contained  in  the Karlsruhe Toolbox for Compiler Construction. The preproces-
  144. sors cg -xz and rpp derive a  parser  specification  and  most  of  a  scanner
  145. specification  from an attribute grammar.  The preprocessors l2r, y2l, and r2l
  146. convert input for lex and yacc into specifications for rex and lalr  and  vice
  147. versa.  All  preprocessors work as filter programs reading input from standard
  148. input and writing output to standard output.  Some preprocessors can read from
  149. a file specified as argument, too.
  150.  
  151. 2.  Specification of Scanner and Parser with an Attribute Grammar
  152.  
  153.      Writing specifications for the scanner  generator  rex  [Gro87]  and  the
  154. parser  generator  lalr  [GrV88]  directly  in the tool specific language is a
  155. practicable method.  However, it has some disadvantages. Most  of  the  tokens
  156. are  specified  twice and their internal representation or code, respectively,
  157. has to be selected and kept consistent, manually. Access to  attributes  using
  158. the  yacc-style  $i  construct  (see e.g. [GrV88]) is less readable and error-
  159. prone in case of changes. The following solution avoids these disadvantages.
  160.  
  161.      Instead of using the tool specific language for rex and lalr directly,  a
  162. language of higher level is used. It replaces the $i construct by named attri-
  163. butes and describes a complete parser and most of a scanner in  one  document.
  164. Two  preprocessors  transform such a specification into the languages directly
  165. understood by rex and lalr.  Fig. 1 shows the data flow using  arrows  between
  166. boxes  and circles.  Boxes represent files or file types and circles represent
  167. tools or preprocessors.  The intermediate file named  Scanner.rpp  by  default
  168. contains  the part of the scanner specification that can be extracted from the
  169. parser specification. Table 1 gives the meaning of the file types used in Fig.
  170. 1 and this manual.
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.             Fig. 1: Data flow during scanner and parser generation
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.                                                                              2
  200.  
  201.  
  202.                         Table 1: Meaning of file types
  203.  
  204.  ___________________________________________________________________________
  205.   file type   meaning
  206.  ___________________________________________________________________________
  207.   .pars       scanner and parser specification (including S-attribution)
  208.   .scan       rest of scanner specification
  209.   .rpp        intermediate data for completion of scanner in .scan
  210.   .rex        scanner specification understood by rex
  211.   .lalr       parser specification understood by lalr
  212.   .ell        input for ell (= input for lalr with EBNF constructs [GrV88])
  213.   .lex        input for lex
  214.   .yacc       input for yacc
  215.   Source      generated module (or linked from library reuse)
  216.   Scanner     generated module
  217.   Parser      generated module
  218.   Errors      generated module (or linked from library reuse)
  219.  ___________________________________________________________________________
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233.            
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.                                                                            
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.      The formalism used to describe parsers (.pars) is  an  extension  of  the
  264. input  language  for  the tools ast [Gro91] and ag [Gro89] (see section 2.1.).
  265. This leads to a rather uniform set of input languages for most  of  the  tools
  266. and simplifies their use. The preprocessor cg -xz transforms a parser specifi-
  267. cation in ag notation into one in lalr notation and extracts most of a scanner
  268. specification.  The parser specification in lalr notation is written on a file
  269. named <Parser>.lalr. <Parser> is substituted by the name of the parser  module
  270. which defaults to Parser.  The extracted scanner specification is written to a
  271. file named <Scanner>.rpp.  <Scanner> is substituted by the name of the scanner
  272. module  which defaults to Scanner.  The rest of the scanner specification must
  273. be written in the language directly understood by rex.  It has to contain  the
  274. part  of  a scanner specification that can not be derived automatically.  This
  275. part is usually rather small and comprises  the  description  of  user-defined
  276. tokens  like  identifiers and numbers, comments, and the computation of attri-
  277. butes for the tokens. A few insertion points are marked to tell the preproces-
  278. sor rpp where to include the generated parts (see section 2.2.).
  279.  
  280. 2.1.  Parser Specification
  281.  
  282.      The input language of ast and ag can be used to generate  a  parser.  The
  283. details  of  this language can be found in the manuals for these tools [Gro89,
  284. Gro91].  The reader should  be  familiar  with  these  documents  because  the
  285. current manual describes primarily the extensions necessary for parser genera-
  286. tion.
  287.  
  288.      The language can describe concrete as well as abstract syntaxes.  Nonter-
  289. minal,  terminal,  and abstract symbols or node types are distinguished by the
  290. definition characters '=',  ':',  and  ':=',  respectively,  and  have  to  be
  291. declared  by default. However, the option j of cg -xz allows undeclared termi-
  292. nal symbols and declares them implicitly.  In any case, terminal symbols  with
  293. attributes have to be declared explicitly.
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.                                                                              3
  306.  
  307.  
  308.      Note, the following names are reserved for keywords and can not  be  used
  309. for grammar symbols.  Unfortunately, some of them occur frequently as keywords
  310. in languages that are being defined.  They should be turned  into  strings  by
  311. surrounding apostrophes:
  312.  
  313.     BEGIN           CLOSE           DECLARE         DEMAND          END
  314.     EVAL            EXPORT          FOR             FUNCTION        GLOBAL
  315.     IGNORE          IMPORT          IN              INH             INHERITED
  316.     INPUT           LEFT            LOCAL           MODULE          NONE
  317.     OUT             OUTPUT          PARSER          PREC            PROPERTY
  318.     REMOTE          REV             REVERSE         RIGHT           RULE
  319.     SCANNER         SELECT          STACK           SUBUNIT         SYN
  320.     SYNTHESIZED     THREAD          TREE            VIEW            VIRTUAL
  321.     VOID
  322.  
  323.  
  324.      The right-hand sides of node types without extensions are interpreted  as
  325. right-hand  sides  of  grammar rules (see e. g. Assign, Call0, Call, and If in
  326. the example below).  The children of the right-hand side form  a  sequence  of
  327. terminal  and  nonterminal  symbols  as  usual.  The names of those node types
  328. serve as rule names.  If a symbol occurs several times on one right-hand side,
  329. it  has  to  be preceded by different selector names (see e. g. the rule named
  330. If).  Attributes in brackets are not interpreted as  grammar  symbols  but  as
  331. attribute declarations representing values to be evaluated during parsing.
  332.  
  333.      Not every name of a node type is interpreted as nonterminal  or  terminal
  334. symbol.   Only  those node types that are used (referenced) on some right-hand
  335. side and the first node type which is regarded as start symbol are treated  as
  336. grammar symbols.  If a node type is defined as nonterminal then all associated
  337. extensions become alternative right-hand sides for  this  nonterminal  symbol.
  338. If a node type is defined as terminal it remains a terminal symbol.  If a node
  339. type is not defined and option j is not set an error message  is  issued.   If
  340. option j is set then undefined node types are implicitly defined as terminals.
  341.  
  342.      The grammar needs not to be reduced. This means it may contain  superflu-
  343. ous  terminal and nonterminal symbols. Symbols are superfluous if they are not
  344. referenced from any rule.  Those symbols are simply ignored and reported as  a
  345. warning.
  346.  
  347.  
  348.  
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356.  
  357.  
  358.  
  359.  
  360.  
  361.  
  362.  
  363.  
  364.  
  365.  
  366.  
  367.  
  368.  
  369.  
  370.                                                                              4
  371.  
  372.  
  373.     Example: input of cg -xz
  374.     Stat            = <
  375.        Assign       = Adr ':=' Expr .
  376.        Calls        = Ident <
  377.           Call0     = .
  378.           Call      = '(' Actuals ')' .
  379.        > .
  380.        If           = IF Expr THEN Then: Stats ELSE Else: Stats 'END' .
  381.     > .
  382.     Expr            = <
  383.        Plus         = Lop: Expr '+' Rop: Expr .
  384.        Times        = Lop: Expr '*' Rop: Expr .
  385.        '()'         = '(' Expr ')' .
  386.        Adr          = <
  387.           Name      = Ident .
  388.           Index     = Adr '[' Expr ']' .
  389.        > .
  390.     > .
  391.  
  392.  
  393.     Example: output of cg -xz
  394.     Stat : Adr ':=' Expr .
  395.     Stat : Ident .
  396.     Stat : Ident '(' Actuals ')' .
  397.     Stat : IF Expr THEN Stats ELSE Stats 'END' .
  398.  
  399.     Expr : Expr '+' Expr .
  400.     Expr : Expr '*' Expr .
  401.     Expr : '(' Expr ')' .
  402.     Expr : Ident .
  403.     Expr : Adr '[' Expr ']' .
  404.  
  405.     Adr  : Ident .
  406.     Adr  : Adr '[' Expr ']' .
  407.  
  408. The rule names and the selector names on the right-hand sides disappear (e. g.
  409. If).  The  extension  formalism  is expanded (e. g. Calls and Adr) - it is not
  410. mapped to chain rules.  The expansion includes the inheritance of children and
  411. attributes  (e. g. Calls).  All node types that are used somewhere become non-
  412. terminal symbols (e. g. Expr and Adr).
  413.  
  414.      The rule names of non-referenced node types  may  be  omitted.  They  are
  415. necessary  for example if modules are used in order to refer from an attribute
  416. computation to a grammar rule.
  417.  
  418.  
  419.  
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.                                                                              5
  435.  
  436.  
  437.     Example without rule names:
  438.     Stat  = -> [Tree: tTree] <
  439.           = Adr ':=' Expr         { Tree := mAssign (Adr:Tree, Expr:Tree);     } .
  440.           = Ident '(' Actuals ')' { Tree := mCall (Ident:Ident, Actuals:Tree); } .
  441.     > .
  442.     Ident : [Ident: tIdent] .
  443.  
  444.  
  445.     Example with rule names:
  446.     Stat      = <
  447.        Assign = Adr ':=' Expr .
  448.        Call   = Ident '(' Actuals ')' .
  449.     > .
  450.     Ident     : [Ident: tIdent] .
  451.     MODULE Tree
  452.     DECLARE Stat = -> [Tree: tTree] .
  453.     Assign    = { Tree := mAssign (Adr:Tree, Expr:Tree);         } .
  454.     Call      = { Tree := mCall (Ident:Ident, Actuals:Tree);     } .
  455.     END Tree
  456.  
  457.  
  458.      Attribute declarations and attribute computations are written exactly  as
  459. for  ast  and  ag.   Attribute  computations  may  be placed everywhere within
  460. right-hand sides, not only at the end. These computations  are  executed  from
  461. left  to right as parsing proceeds. They may only make use of those attributes
  462. that have already been computed before  or  to  the  left,  respectively.  The
  463. extension  or  inheritance  mechanism for right-hand sides, attribute declara-
  464. tions, and attribute computations  is  available.   The  default  computations
  465. (copy  rules)  for  synthesized attributes are available, too. A specification
  466. may be separated into several modules. There could for example be modules  for
  467. the  concrete  syntax,  for  the attribute declarations, and for the attribute
  468. computations. It is even possible to distribute the mentioned kinds of  infor-
  469. mation into several modules.
  470.  
  471.      Attribute declarations and attribute computations with  named  attributes
  472. replace  the  explicit  declaration of the type tParsAttribute and the $i con-
  473. struct. The  attribute  declarations  are  transformed  automatically  into  a
  474. declaration of the type tParsAttribute.  The attribute computations in the new
  475. style are more readable and robust against changes. The given attribute compu-
  476. tations are checked for completeness and whether the resulting attribute gram-
  477. mar obeys the SAG property. Only attribute grammars  with  synthesized  attri-
  478. butes can be evaluated during parsing.
  479.  
  480.      Every terminal has a predefined attribute named Position of  type  tPosi-
  481. tion.   This type is a user defined struct (record) type and has to contain at
  482. least the members Line and Column.  This attribute describes the source  coor-
  483. dinates  of  every  token  and  it  is computed automatically by rex generated
  484. scanners.  The values of all other attributes of terminals have to be supplied
  485. by  the  scanner by user specified computations. Still, attribute computations
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.                                                                              6
  497.  
  498.  
  499. for those attributes (except Position) have to  be  specified  in  the  parser
  500. specification,  too.  They  are used to generate the procedure ErrorAttribute.
  501. This procedure is called by the parser whenever tokens are inserted  in  order
  502. to  repair  syntax errors. The procedure and therefore the mentioned attribute
  503. computations have to supply default values for the attributes of tokens.
  504.  
  505.      The right-hand side of a node type or a grammar rule,  respectively,  may
  506. contain  actions to be executed during parsing. These actions may be placed at
  507. the end of the right-hand side or anywhere between the  right-hand  side  ele-
  508. ments.  In any case these actions are executed from left to right according to
  509. the progress of parsing. The syntax of the actions is the one defined for  the
  510. attribute  computations  of  ag.   It is assumed that most of the actions will
  511. compute attributes.  Actions which are not attribute computations are possible
  512. but have to be written as some kind of CHECK statement:
  513.  
  514.     => statement ;   or    => { statement_sequence } ;
  515.  
  516.  
  517.      The following extensions of the language of  ast  and  ag  are  used  for
  518. parser  generation, only.  A grammar may be optionally headed by names for the
  519. modules to be generated:
  520.  
  521.     SCANNER Name PARSER Name
  522.  
  523. The first identifier specifies the module name of the scanner to  be  used  by
  524. the  parser.   The  second identifier specifies a name which is used to derive
  525. the names of the parsing module, the parsing routine, the parse  tables,  etc.
  526. If the names are missing they default to Scanner and Parser.  In this document
  527. we refer to these names by <Scanner> and <Parser>.  The  parser  name  may  be
  528. followed  by  a  set  of  target  code  sections which is copied unchecked and
  529. unchanged to the input of the parser generator or the parser  module,  respec-
  530. tively:
  531.  
  532.     SCANNER Name
  533.     PARSER  Name
  534.     IMPORT { target_code }
  535.     EXPORT { target_code }
  536.     GLOBAL { target_code }
  537.     LOCAL  { target_code }
  538.     BEGIN  { target_code }
  539.     CLOSE  { target_code }
  540.  
  541.  
  542.      The precedence and associativity for operator  tokens  can  be  specified
  543. after  the  keyword PREC using LEFT, RIGHT, and NONE for left-, right-, and no
  544. associativity. Each group headed by one of the latter  three  keywords  intro-
  545. duces  a  new  group of tokens with increasing precedence.  The precedence and
  546. associativity information is copied unchanged to the parser generator.
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.                                                                              7
  562.  
  563.  
  564.     Example:
  565.     PREC LEFT MONOP
  566.          NONE SEQ
  567.          LEFT '+' '-'
  568.          LEFT '*' '/' MOD
  569.  
  570. The precedence and associativity information is usually propagated  implicitly
  571. to  the  grammar rules by taking it from the right-most token in a rule. Rules
  572. without an operator token can get the precedence  and  associativity  from  an
  573. operator token by adding a PREC clause at the end of a right-hand side.
  574.  
  575.     Example:
  576.     Expr = <
  577.          = Expr Expr PREC SEQ .   /* explicit  prec. + assoc. of SEQ          */
  578.          = '-'  Expr PREC MONOP . /* overwrite prec. + assoc. of '-' by MONOP */
  579.          = Expr '+' Expr .        /* implicit  prec. + assoc. of '+'          */
  580.          = Expr '-' Expr .        /* implicit  prec. + assoc. of '-'          */
  581.     > .
  582.  
  583.  
  584.      Tokens or terminal symbols are mapped automatically to integer numbers to
  585. be  used as internal representation. This mapping can be overwritten by expli-
  586. citly giving codes for terminals.
  587.  
  588.     Example:
  589.     Ident    :   [Ident: tIdent] .   /* implicitly coded      */
  590.     IntConst : 5 [Value: int   ] .   /* explicitly coded as 5 */
  591.  
  592.  
  593.      The attribute declarations for terminals are turned into a declaration of
  594. the  type tScanAttribute.  The scanner communicates attribute values of termi-
  595. nals to the parser using a global variable called Attribute which is  of  this
  596. type. This type is a union type (variant record) with one member (variant) for
  597. each terminal with attributes. The names of the terminals are  taken  for  the
  598. names of these members (variants). However, this leads to problems if the ter-
  599. minals are named by strings or by keywords  of  the  implementation  language.
  600. Therefore  terminals may have two names. The second one is used as member name
  601. in the type tScanAttribute.  The predefined attribute Position mentioned above
  602. is  always  included  in  this  type.  Assignments  of attribute values in the
  603. scanner therefore have to use two selections to describe an attribute:
  604.  
  605.     Attribute.<selector name>.<attribute name> = ...
  606.  
  607.  
  608.     Example:
  609.     definition of terminals including attributes and member selectors in the parser specification
  610.     Ident        : [Ident: tIdent] .   /* selector name: Ident   */
  611.     ':=' sAssign : [Ident: tIdent] .   /* selector name: sAssign */
  612.     TRUE sTRUE   : [Ident: tIdent] .   /* selector name: sTRUE   */
  613.     '..'         : [Ident: tIdent] .   /* selector name: yy17    */
  614.  
  615.  
  616.  
  617.  
  618.  
  619.  
  620.  
  621.  
  622.  
  623.  
  624.                                                                              8
  625.  
  626.  
  627.     access of attributes in the scanner specification
  628.     Attribute.Ident.Ident
  629.     Attribute.sAssign.Ident
  630.     Attribute.sTRUE.Ident
  631.     Attribute.yy17.Ident
  632.  
  633.  
  634.     access of attributes in the parser specification (at node directly)
  635.     Ident                     Position
  636.  
  637.  
  638.     access of attributes in the parser specification (from a child node)
  639.     Ident:Ident               Ident:Position
  640.     ':=':Ident                ':=':Position
  641.     TRUE:Ident                TRUE:Position
  642.     '..':Ident                '..':Position
  643.  
  644.  
  645.      The preprocessor for the parser specification is part of the program  cg.
  646. It is called by the following command:
  647.  
  648.     cg -xzvjc [ Parser.pars ]
  649.  
  650. The input is read either from the file given  as  argument  or  from  standard
  651. input  if  the  argument  is  missing.  The  output is written to a file named
  652. <Parser>.lalr.  The program is controlled by the following options:
  653.  
  654.     x   generate scanner specification for rex
  655.     z   generate parser  specification for lalr
  656.     v   omit actions in the generated parser specification
  657.     j   allow undefined node types; define implicitly as terminals
  658.     c   generate C source code (default is Modula-2)
  659.  
  660.  
  661.      Appendix 1 of the ag manual [Gro89] contains the complete  formal  syntax
  662. understood  by  the  program  cg.   Appendix  2  of this manual shows a parser
  663. specification for the example language  MiniLAX.   It  separates  context-free
  664. grammar and attribute computations in two modules.  The attribute computations
  665. in the module Tree use one attribute also called Tree and  describe  the  con-
  666. struction  of  an  abstract syntax tree by calling functions generated by ast.
  667. The implementation language is C.
  668.  
  669. 2.2.  Scanner Specification
  670.  
  671.      The scanner specification has to contain only those parts that can not be
  672. extracted automatically from the parser specification. This is as already men-
  673. tioned above the description  of  user-defined  tokens  like  identifiers  and
  674. numbers,  comments, and the computation of attributes for the tokens. The for-
  675. malism to describe this fragmentary scanner specification (.scan) is the input
  676. language of rex [Gro87].  It may contain three insertion points which instruct
  677. the preprocessor rpp (rex preprocessor) to include  certain  generated  parts.
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.                                                                              9
  689.  
  690.  
  691. Moreover,  tokens  in  return statements can be denoted by the same strings or
  692. identifiers as in the parser specification.
  693.  
  694.     INSERT tScanAttribute
  695.  
  696. in the EXPORT section is replaced by the generated  declaration  of  the  type
  697. tScanAttribute  and the head or external declaration of the procedure ErrorAt-
  698. tribute.
  699.  
  700.     INSERT ErrorAttribute
  701.  
  702. in the GLOBAL section is replaced by  the  body  of  the  generated  procedure
  703. ErrorAttribute.
  704.  
  705.      The third insertion point lies in the RULE section and has the  following
  706. syntax  (only the brackets [ ] are used as meta characters and denote optional
  707. parts):
  708.  
  709.     INSERT RULES [CASE-INSENSITIVE] [[NOT] #<start_states>#] [{ <target_code> }]
  710.  
  711. It is replaced by as many rules as there are  tokens  extracted  automatically
  712. from the parser specification. Every rule has the following format:
  713.  
  714.     NOT # <start_states> # <token> : { <target_code> return <code>; }
  715.  
  716. The start states including the keyword NOT and the target  code  are  optional
  717. and  are  copied  to  the  generated rule as indicated. If CASE-INSENSITIVE is
  718. specified, the regular expressions for the tokens  are  constructed  to  match
  719. lower  as  well  as  upper  case letters.  Note, only rules for tokens without
  720. explicitly declared attributes are constructed automatically.
  721.  
  722.      Within a rule, return (or RETURN)  statements  are  used  to  report  the
  723. internal code of a recognized token. The expression of those statements can be
  724. any expression of the implementation language or a  string  or  an  identifier
  725. used  in  the parser specification.  The latter are replaced by their internal
  726. representation.
  727.  
  728.     Example:
  729.     return 5;
  730.     return Ident;
  731.     return ':=';
  732.  
  733.  
  734.      The program rpp is called by the following command:
  735.  
  736.     rpp [ Scanner.rpp ] < Scanner.scan > Scanner.rex
  737.  
  738. The fragmentary scanner  specification  is  read  from  standard  input.   The
  739. scanner  specification  extracted from the parser specification is read from a
  740. file given as argument. This argument is optional and defaults to Scanner.rpp.
  741. The  scanner  specification  understood  by rex is written on standard output.
  742. The basename Scanner in the command line above is usually substituted  by  the
  743.  
  744.  
  745.  
  746.  
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753.                                                                             10
  754.  
  755.  
  756. name of the scanner module.
  757.  
  758.      Appendix 1 contains a scanner  specification  for  the  example  language
  759. MiniLAX.  It uses C as implementation language.
  760.  
  761.  
  762.       Fig. 2: Conversion programs for scanner and parser specifications
  763.  
  764.  
  765. 3.  Conversion of Scanner and Parser Specifications
  766.  
  767. 3.1.  Input Languages
  768.  
  769.      The input languages of rex and lalr have been designed to be as  readable
  770. as  possible.  Although  they  contain  the same information as inputs for lex
  771. [Les75] and yacc [Joh75] they are syntactically incompatible. Several  conver-
  772. sion  programs allow the transformation of input for rex and lalr to input for
  773. lex and yacc or vice versa.  Fig.2 shows the possible conversions for  scanner
  774. and parser specifications.  Table 2 lists the existing filter programs and the
  775. types of their input and output files.
  776.  
  777.      The option '-v' instructs y2l and cg to omit the semantic actions in  the
  778. produced  output.   The  following restrictions or problems are known to exist
  779. because they can not be mapped to the target tool:
  780.  
  781. l2r
  782.  
  783. -    yymore
  784.  
  785. -    REJECT
  786.  
  787. -    yywrap    (redirection can be done with rex, but differently)
  788.  
  789. -    %T        (specification of the character set is not possible)
  790.  
  791.  
  792.  
  793.  
  794.                     Table 2: Filters for input conversion
  795.  
  796.                           _________________________
  797.                            filter   input   output
  798.                           _________________________
  799.                            l2r      .lex    .rex
  800.                            r2l      .rex    .lex
  801.                            y2l      .yacc   .lalr
  802.                            cg -u    .pars   .yacc
  803.                            cg -z    .pars   .lalr
  804.                            bnf      .ell    .lalr
  805.                           _________________________
  806.                          
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.                                  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.                                          
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.                                                   
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.                                                                             11
  849.  
  850.  
  851. r2l
  852.  
  853. -    yyPrevious
  854.  
  855. -    EOF       (specifies actions to be performed upon reaching end of file)
  856.  
  857. y2l
  858.  
  859. -    The conversion of token definitions may not be completely automatic.
  860.  
  861. -    If scanning depends on information collected by the parser  then  parsers
  862.      generated  by  yacc  and  lalr may behave differently because they do not
  863.      agree upon the order or timing, respectively, of the  execution  of  read
  864.      (shift) and reduce actions.
  865.  
  866. bnf
  867.  
  868. -    The attribute computations for ell and lalr are  different  and  are  not
  869.      converted.
  870.  
  871. 3.2.  Interfaces
  872.  
  873.      The interfaces of scanners and parsers generated by lex/yacc and rex/lalr
  874. are  incompatible. The differences are primarily caused by different names for
  875. the external (exported) objects. Table 3 lists  the  interface  objects.   The
  876. interfaces  of  the  scanners  and  parsers  generated  by rex and lalr can be
  877. switched from the default as listed in Table 3 to an approximation of the  lex
  878. and yacc interfaces. This is controlled by cpp commands:
  879.  
  880.     # define lex_interface
  881.  
  882. in the EXPORT section of a rex specification selects a lex-style interface for
  883.  
  884.             Table 3: Interfaces of generated scanners and parsers
  885.  
  886. _________________________________________________________________________________________________
  887.  object             yacc/lex          lalr/rex
  888. _________________________________________________________________________________________________
  889.  parse routine      int yyparse ();   int Parser ();
  890.  stack size         YYMAXDEPTH        yyInitStackSize
  891.  attribute type     YYSTYPE           tParsAttribute
  892. _________________________________________________________________________________________________
  893.  global attribute   YYSTYPE yylval;   tScanAttribute Attribute;
  894. _________________________________________________________________________________________________
  895.  position type                        typedef struct { short Line, Column; ... } tPosition;
  896.  attribute type                       typedef struct { tPosition Position; ... } tScanAttribute;
  897.  scanner routine    int yylex ();     int GetToken ();
  898.  error repair                         void ErrorAttribute ();
  899.  line number        int yylineno;     member Attribute.Position.Line
  900.  token buffer       char yytext [];
  901.  token length       int yyleng;
  902. _________________________________________________________________________________________________
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.                  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.                                    
  930.  
  931.  
  932.  
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.                                                                                                 
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.                                                                             12
  969.  
  970.  
  971. the scanner.
  972.  
  973.     # define lex_interface
  974.  
  975. in the EXPORT section of a lalr specification tells the parser to use  a  lex-
  976. style interface for the scanner.
  977.  
  978.     # define yacc_interface
  979.  
  980. in the EXPORT section of a lalr specification selects a  yacc-style  interface
  981. for the parser.
  982.  
  983.      The output of the preprocessors l2r and y2l  automatically  selects  lex-
  984. and yacc-style interfaces. The following problems are known, currently:
  985.  
  986. -    The output of l2r provides the matched string in the array yytext  to  be
  987.      used in action statements. This is done by calling the procedure Getword.
  988.      However, many actions do not need yytext.  Deleting superfluous calls  of
  989.      Getword will make the scanner significantly faster.
  990.  
  991. -    Access to the line counter yylineno has to be replaced by access to
  992.  
  993.          Attribute.Position.Line
  994.  
  995.  
  996. -    If both, scanner and parser specification have been converted by l2r  and
  997.      y2l in order to be fed into rex and lalr, the two preprocessor statements
  998.      which define lex_interface should be deleted in order to select the stan-
  999.      dard  interface. This offers more comfort with respect to the information
  1000.      about the source position.
  1001.  
  1002. Acknowledgements
  1003.  
  1004.      The preprocessor bnf  has  been  implemented  by  Bertram  Vielsack.  The
  1005. preprocessors  y2l,  l2r,  rpp,  and  cg  -xz  have been implemented by Thomas
  1006. Mueller.
  1007.  
  1008. References
  1009.  
  1010. [Gro87]
  1011.      J. Grosch, Rex - A Scanner Generator, Compiler Generation Report  No.  5,
  1012.      GMD Forschungsstelle an der Universitat Karlsruhe, Dec. 1987.
  1013.  
  1014. [GrV88]
  1015.      J. Grosch and B. Vielsack, The Parser Generators Lalr and  Ell,  Compiler
  1016.      Generation   Report  No.  8,  GMD  Forschungsstelle  an  der  Universitat
  1017.      Karlsruhe, Apr. 1988.
  1018.  
  1019. [Gro89]
  1020.      J. Grosch, Ag - An Attribute  Evaluator  Generator,  Compiler  Generation
  1021.      Report  No.  16,  GMD Forschungsstelle an der Universitat Karlsruhe, Aug.
  1022.      1989.
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033.                                                                             13
  1034.  
  1035.  
  1036. [Gro91]
  1037.      J. Grosch,  Ast  -  A  Generator  for  Abstract  Syntax  Trees,  Compiler
  1038.      Generation  Report  No.  15,  GMD  Forschungsstelle  an  der  Universitat
  1039.      Karlsruhe, Sep. 1991.
  1040.  
  1041. [Joh75]
  1042.      S. C. Johnson, Yacc -  Yet Another  Compiler-Compiler,  Computer  Science
  1043.      Technical  Report  32, Bell Telephone Laboratories, Murray Hill, NJ, July
  1044.      1975.
  1045.  
  1046. [Les75]
  1047.      M. E. Lesk,  LEX  -  A  Lexical  Analyzer  Generator,  Computing  Science
  1048.      Technical Report 39, Bell Telephone Laboratories, Murray Hill, NJ, 1975.
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096.  
  1097.  
  1098.                                                                             14
  1099.  
  1100.  
  1101. Appendix 1: Scanner Specification for MiniLAX
  1102.  
  1103. EXPORT  {
  1104. # include "Idents.h"
  1105. # include "Positions.h"
  1106. INSERT tScanAttribute
  1107. }
  1108. GLOBAL  {
  1109. # include <math.h>
  1110. # include "Memory.h"
  1111. # include "StringMem.h"
  1112. # include "Idents.h"
  1113. # include "Errors.h"
  1114. INSERT ErrorAttribute
  1115. }
  1116. LOCAL   { char Word [256]; }
  1117. DEFAULT {
  1118. MessageI ("illegal character", xxError, Attribute.Position, xxCharacter, TokenPtr);
  1119. }
  1120. EOF     {
  1121.    if (yyStartState == Comment)
  1122.       Message ("unclosed comment", xxError, Attribute.Position);
  1123. }
  1124. DEFINE  digit   = {0-9} .
  1125.         letter  = {a-z A-Z} .
  1126. START   Comment
  1127. RULE
  1128.           "(*"  :- {yyStart (Comment);}
  1129. #Comment# "*)"  :- {yyStart (STD);}
  1130. #Comment# "*" | - {*\t\n} + :- {}
  1131. #STD# digit +   : {(void) GetWord (Word);
  1132.                    Attribute.IntegerConst.Integer = atoi (Word);
  1133.                    return IntegerConst;}
  1134. #STD# digit * "." digit + (E {+\-} ? digit +) ?
  1135.                 : {(void) GetWord (Word);
  1136.                    Attribute.RealConst.Real = atof ((char *) Word);
  1137.                    return RealConst;}
  1138. INSERT RULES #STD#
  1139. #STD# letter (letter | digit) *
  1140.                 : {Attribute.Ident.Ident = MakeIdent (TokenPtr, TokenLength);
  1141.                    return Ident;}
  1142.  
  1143.  
  1144.  
  1145.  
  1146.  
  1147.  
  1148.  
  1149.  
  1150.  
  1151.  
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.                                                                             15
  1158.  
  1159.  
  1160. Appendix 2: Parser Specification for MiniLAX
  1161.  
  1162. PARSER
  1163.  
  1164. GLOBAL {# include "Idents.h" }
  1165.  
  1166. BEGIN  { BeginScanner (); }
  1167.  
  1168. PREC    LEFT    '<'                             /* operator precedence  */
  1169.         LEFT    '+'
  1170.         LEFT    '*'
  1171.         LEFT    NOT
  1172.  
  1173. PROPERTY INPUT
  1174.  
  1175. RULE                                            /* concrete syntax      */
  1176.  
  1177. Prog            = PROGRAM Ident ';' 'DECLARE' Decls 'BEGIN' Stats 'END' '.' .
  1178. Decls           = <
  1179.    Decls1       = Decl .
  1180.    Decls2       = Decls ';' Decl .
  1181. > .
  1182. Decl            = <
  1183.    Var          = Ident ':' Type .
  1184.    Proc0        = PROCEDURE Ident ';' 'DECLARE' Decls 'BEGIN' Stats 'END' .
  1185.    Proc         = PROCEDURE Ident '(' Formals ')' ';'
  1186.                                       'DECLARE' Decls 'BEGIN' Stats 'END' .
  1187. > .
  1188. Formals         = <
  1189.    Formals1     = Formal .
  1190.    Formals2     = Formals ';' Formal .
  1191. > .
  1192. Formal          = <
  1193.    Value        = Ident ':' Type .
  1194.    Ref          = VAR Ident ':' Type .
  1195. > .
  1196. Type            = <
  1197.    Int          = INTEGER .
  1198.    Real         = REAL .
  1199.    Bool         = BOOLEAN .
  1200.    Array        = ARRAY '[' Lwb: IntegerConst '..' Upb: IntegerConst ']' OF Type .
  1201. > .
  1202. Stats           = <
  1203.    Stats1       = Stat .
  1204.    Stats2       = Stats ';' Stat .
  1205. > .
  1206. Stat            = <
  1207.    Assign       = Adr ':=' Expr .
  1208.    Call0        = Ident .
  1209.    Call         = Ident '(' Actuals ')' .
  1210.    If           = IF Expr THEN Then: Stats ELSE Else: Stats 'END' .
  1211.    While        = WHILE Expr DO Stats 'END' .
  1212.    Read         = READ '(' Adr ')' .
  1213.  
  1214.  
  1215.  
  1216.  
  1217.  
  1218.  
  1219.  
  1220.  
  1221.  
  1222.  
  1223.                                                                             16
  1224.  
  1225.  
  1226.    Write        = WRITE '(' Expr ')' .
  1227. > .
  1228. Actuals         = <
  1229.    Expr1        = Expr .
  1230.    Expr2        = Actuals ',' Expr .
  1231. > .
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.  
  1261.  
  1262.  
  1263.  
  1264.  
  1265.  
  1266.  
  1267.  
  1268.  
  1269.  
  1270.  
  1271.  
  1272.  
  1273.  
  1274.  
  1275.  
  1276.  
  1277.  
  1278.  
  1279.  
  1280.  
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286.  
  1287.  
  1288.                                                                             17
  1289.  
  1290.  
  1291. Expr            = <
  1292.    Less         = Lop: Expr '<' Rop: Expr .
  1293.    Plus         = Lop: Expr '+' Rop: Expr .
  1294.    Times        = Lop: Expr '*' Rop: Expr .
  1295.    Not          = NOT Expr .
  1296.    '()'         = '(' Expr ')' .
  1297.    IConst       = IntegerConst .
  1298.    RConst       = RealConst .
  1299.    False        = FALSE .
  1300.    True         = TRUE .
  1301.    Adr          = <
  1302.       Name      = Ident .
  1303.       Index     = Adr '[' Expr ']' .
  1304.    > .
  1305. > .
  1306.  
  1307.                                         /* terminals (with attributes)  */
  1308.  
  1309. Ident           : [Ident: tIdent] { Ident       := NoIdent      ; } .
  1310. IntegerConst    : [Integer      ] { Integer     := 0            ; } .
  1311. RealConst       : [Real : float ] { Real        := 0.0          ; } .
  1312.  
  1313. MODULE Tree
  1314.                         /* import functions for tree construction       */
  1315. PARSER GLOBAL   {
  1316. # include "Tree.h"
  1317.  
  1318. tTree  nInteger, nReal, nBoolean;
  1319. }
  1320.  
  1321. BEGIN   {
  1322.    nInteger     = mInteger      ();
  1323.    nReal        = mReal         ();
  1324.    nBoolean     = mBoolean      ();
  1325. }
  1326.  
  1327.  
  1328.  
  1329.  
  1330.  
  1331.  
  1332.  
  1333.  
  1334.  
  1335.  
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350.  
  1351.  
  1352.  
  1353.                                                                             18
  1354.  
  1355.  
  1356.                         /* attributes for tree construction             */
  1357. DECLARE
  1358.   Decls Decl Formals Formal Type Stats Stat Actuals Expr = [Tree: tTree] .
  1359.  
  1360. RULE                    /* tree construction =                          */
  1361.                         /* mapping: concrete syntax -> abstract syntax  */
  1362.  
  1363. Prog    = { => { TreeRoot = mMiniLax (mProc (mNoDecl (), Ident:Ident,
  1364.                  Ident:Position, mNoFormal (), ReverseTree (Decls:Tree),
  1365.                  ReverseTree (Stats:Tree)));};                                  } .
  1366. Decls1  = { Tree := {Decl:Tree->\Decl.Next = mNoDecl (); Tree = Decl:Tree;};    } .
  1367. Decls2  = { Tree := {Decl:Tree->\Decl.Next = Decls:Tree; Tree = Decl:Tree;};    } .
  1368. Var     = { Tree := mVar (NoTree, Ident:Ident, Ident:Position, mRef (Type:Tree));}.
  1369. Proc0   = { Tree := mProc (NoTree, Ident:Ident, Ident:Position, mNoFormal (),
  1370.                     ReverseTree (Decls:Tree), ReverseTree (Stats:Tree));        } .
  1371. Proc    = { Tree := mProc (NoTree, Ident:Ident, Ident:Position, ReverseTree
  1372.            (Formals:Tree), ReverseTree (Decls:Tree), ReverseTree (Stats:Tree)); } .
  1373. Formals1= { Tree := {Formal:Tree->\Formal.Next = mNoFormal ();
  1374.                     Tree = Formal:Tree;};                                       } .
  1375. Formals2= { Tree := {Formal:Tree->\Formal.Next = Formals:Tree;
  1376.                     Tree = Formal:Tree;};                                       } .
  1377. Value   = { Tree := mFormal (NoTree, Ident:Ident, Ident:Position,
  1378.                     mRef (Type:Tree));                                          } .
  1379. Ref     = { Tree := mFormal (NoTree, Ident:Ident, Ident:Position,
  1380.                     mRef (mRef (Type:Tree)));                                   } .
  1381. Int     = { Tree := nInteger;                                                   } .
  1382. Real    = { Tree := nReal;                                                      } .
  1383. Bool    = { Tree := nBoolean;                                                   } .
  1384. Array   = { Tree := mArray (Type:Tree, Lwb:Integer, Upb:Integer, Lwb:Position); } .
  1385. Stats1  = { Tree := {Stat:Tree->\Stat.Next = mNoStat (); Tree = Stat:Tree;};    } .
  1386. Stats2  = { Tree := {Stat:Tree->\Stat.Next = Stats:Tree; Tree = Stat:Tree;};    } .
  1387. Assign  = { Tree := mAssign (NoTree, Adr:Tree, Expr:Tree, ':=':Position);       } .
  1388. Call0   = { Tree := mCall (NoTree, mNoActual (Ident:Position), Ident:Ident,
  1389.                     Ident:Position);                                            } .
  1390. Call    = { Tree := mCall (NoTree, ReverseTree (Actuals:Tree), Ident:Ident,
  1391.                     Ident:Position);                                            } .
  1392. If      = { Tree := mIf (NoTree, Expr:Tree, ReverseTree (Then:Tree),
  1393.                     ReverseTree (Else:Tree));                                   } .
  1394. While   = { Tree := mWhile (NoTree, Expr:Tree, ReverseTree (Stats:Tree));       } .
  1395. Read    = { Tree := mRead (NoTree, Adr:Tree);                                   } .
  1396. Write   = { Tree := mWrite (NoTree, Expr:Tree);                                 } .
  1397. Expr1   = { Tree := mActual (mNoActual (Expr:Tree->\Expr.Pos), Expr:Tree);      } .
  1398. Expr2   = { Tree := mActual (Actuals:Tree, Expr:Tree);                          } .
  1399. Less    = { Tree := mBinary ('<':Position, Lop:Tree, Rop:Tree, Less);           } .
  1400. Plus    = { Tree := mBinary ('+':Position, Lop:Tree, Rop:Tree, Plus);           } .
  1401. Times   = { Tree := mBinary ('*':Position, Lop:Tree, Rop:Tree, Times);          } .
  1402. Not     = { Tree := mUnary (NOT:Position, Expr:Tree, Not);                      } .
  1403. IConst  = { Tree := mIntConst (IntegerConst:Position, IntegerConst:Integer);    } .
  1404. RConst  = { Tree := mRealConst (RealConst:Position, RealConst:Real);            } .
  1405. False   = { Tree := mBoolConst (FALSE:Position, false);                         } .
  1406. True    = { Tree := mBoolConst (TRUE:Position, true);                           } .
  1407. Name    = { Tree := mIdent (Ident:Position, Ident:Ident);                       } .
  1408. Index   = { Tree := mIndex ('[':Position, Adr:Tree, Expr:Tree);                 } .
  1409.  
  1410.  
  1411.  
  1412.  
  1413.  
  1414.  
  1415.  
  1416.  
  1417.  
  1418.  
  1419.                                                                             19
  1420.  
  1421.  
  1422. END Tree
  1423.  
  1424.  
  1425.  
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449.  
  1450.  
  1451.  
  1452.  
  1453.  
  1454.  
  1455.  
  1456.  
  1457.  
  1458.  
  1459.  
  1460.  
  1461.  
  1462.  
  1463.  
  1464.  
  1465.  
  1466.  
  1467.  
  1468.  
  1469.  
  1470.  
  1471.  
  1472.  
  1473.  
  1474.  
  1475.  
  1476.  
  1477.  
  1478.  
  1479.  
  1480.  
  1481.  
  1482.  
  1483.  
  1484.                                                                              1
  1485.  
  1486.  
  1487. Contents
  1488.  
  1489. 1.      Introduction ....................................................    1
  1490. 2.      Specification of Scanner and Parser with an Attribute  Grammar
  1491.      ....................................................................    1
  1492. 2.1.    Parser Specification ............................................    2
  1493. 2.2.    Scanner Specification ...........................................    8
  1494. 3.      Conversion of Scanner and Parser Specifications .................   10
  1495. 3.1.    Input Languages .................................................   10
  1496. 3.2.    Interfaces ......................................................   11
  1497.         References ......................................................   12
  1498.         Appendix 1: Scanner Specification for MiniLAX ...................   14
  1499.         Appendix 2: Parser Specification for MiniLAX ....................   15
  1500.  
  1501.  
  1502.  
  1503.  
  1504.  
  1505.  
  1506.  
  1507.  
  1508.  
  1509.  
  1510.  
  1511.  
  1512.  
  1513.  
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.  
  1520.  
  1521.  
  1522.  
  1523.  
  1524.  
  1525.  
  1526.  
  1527.  
  1528.  
  1529.  
  1530.  
  1531.  
  1532.  
  1533.  
  1534.  
  1535.  
  1536.  
  1537.  
  1538.  
  1539.  
  1540.  
  1541.  
  1542.  
  1543.  
  1544.  
  1545.